import * as crypto from 'crypto'
import { HttpService } from '@nestjs/axios'
import { Injectable } from '@nestjs/common'
import { InjectRepository } from '@nestjs/typeorm'
import { lastValueFrom } from 'rxjs'
import { Repository } from 'typeorm'
import { BaseService } from '@/common/base/base.service'
import { BaiDuToken, QiHooKey, QiHooSecret } from '@/config/monitor.config'
import { PlayerUser } from '../user/entities/player-user.entity'
import { SubMonitorDto } from './dto/monitor.dto'
import { MonitorEntity } from './entities/monitor.entity'

export interface HttpRequestOptions {
  method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'get' | 'post' | 'put' | 'delete'
  url: string
  // 带在 body 中
  params?: any
  // 带在 url 中
  query?: Record<string, any>
  headers?: Parameters<HttpService['request']>[0]['headers']
}

export interface IQihooResponse {
  errno: number
  error: string
}

export interface IBaiduResponse {
  header: {
    desc: string
    errors: { code: number, message: string, position: string }[]
    status: number
  }
}

@Injectable()
export class MonitorService extends BaseService<MonitorEntity, 'monitorId'> {
  /**
   * 生成签名
   */
  private readonly generateSign = (params: Record<string, any>): string => {
    const json = JSON.stringify(params)
    const signSource = QiHooSecret + json
    return crypto.createHash('md5').update(signSource, 'utf8').digest('hex')
  }

  private async request<T>(options: HttpRequestOptions): Promise<T> {
    const { method, url, query, params, headers } = options

    const querySearch = new URLSearchParams(query)
    const resultUrl = `${url}?${querySearch.toString()}`

    const response = await lastValueFrom(
      this.httpService.request<T>({
        method,
        data: params,
        headers,
        url: resultUrl,
      }),
    )
    return response.data
  }

  constructor(
    @InjectRepository(MonitorEntity)
    private readonly monitorRepository: Repository<MonitorEntity>,
    @InjectRepository(PlayerUser)
    private readonly playerUserRepository: Repository<PlayerUser>,
    private httpService: HttpService,
  ) {
    super(monitorRepository)
  }

  async onSubmitForQihoo(body: SubMonitorDto): Promise<ApiResponseData> {
    const params = {
      data: { request_time: Date.now(), data_industry: 'ocpc_ps_convert', data_detail: JSON.parse(body.onlyId) },
    }
    const sign = this.generateSign(params)

    const response = await this.request<IQihooResponse>({
      method: 'POST',
      url: 'https://convert.dop.360.cn/uploadWebConvert',
      params,
      headers: {
        'Content-Type': 'application/json;charset=utf-8',
        'App-Key': QiHooKey,
        'App-Sign': sign,
      },
    })

    if (response.errno === 0) {
      const playUser = await this.playerUserRepository.findOne({
        where: {
          phone: body.phone,
        },
      })
      await this.monitorRepository.save({
        ...body,
        eventType: params.data.data_detail.event,
        userUid: playUser?.uid,
      })
    }
    else {
      return {
        code: 1002,
        msg: response.error,
        config: {
          customResponse: true,
        },
      }
    }
  }

  async onSubmitForBaidu(body: SubMonitorDto): Promise<ApiResponseData> {
    const params = {
      token: BaiDuToken,
      conversionTypes: JSON.parse(body.onlyId),
    }
    console.log('[ params ] >', params)
    const response = await this.request<IBaiduResponse>({
      method: 'POST',
      url: 'https://ocpc.baidu.com/ocpcapi/api/uploadConvertData',
      params,
      headers: {
        'Content-Type': 'application/json;charset=utf-8',
      },
    })
    console.log(response.header.status)
    if (response.header.status === 0) {
      const playUser = await this.playerUserRepository.findOne({
        where: {
          phone: body.phone,
        },
      })
      await this.monitorRepository.save({
        ...body,
        eventType: Array.isArray(params.conversionTypes)
          ? params.conversionTypes
              .map(item => item.newType ?? '')
              .filter(Boolean)
              .join('、')
          : JSON.stringify(params.conversionTypes),
        userUid: playUser?.uid,
      })
    }
    else {
      return {
        code: 1002,
        msg: response.header.errors[0]?.message,
        config: {
          customResponse: true,
        },
      }
    }
  }
}
